package com.hooper.dp.utils;

import lombok.Data;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;

import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static com.hooper.dp.constant.CommonConstant.*;

/**
 * @author Tim Hooper
 * @version 1.0
 * @time 2023/02/25/19:04
 */

@Data
public class RedisLockUtil {

    private StringRedisTemplate stringRedisTemplate;
    private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;

    /**
     * 每个线程都拥有自己唯一的id，作为锁的值
     */
    public static final String LOCK_ID_PREFIX = "lock:" + UUID.randomUUID() + "-";

    static {
        UNLOCK_SCRIPT = new DefaultRedisScript<>();
        UNLOCK_SCRIPT.setResultType(Long.class);
        UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
    }

    public RedisLockUtil(StringRedisTemplate stringRedisTemplate, String lockKey) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.lockKey = LOCK_KEY + lockKey;
    }

    private String lockKey;

    public boolean tryLock() {
        String value = LOCK_ID_PREFIX + Thread.currentThread().getId();
        return Boolean.TRUE.equals(stringRedisTemplate.opsForValue().
                setIfAbsent(lockKey, value, DEFAULT_LOCK_TTL, TimeUnit.SECONDS));
    }

    public void unlock() {
        stringRedisTemplate.execute(UNLOCK_SCRIPT,
                Collections.singletonList(lockKey),
                //判断是否是当前线程自己的锁
                LOCK_ID_PREFIX + Thread.currentThread().getId());
    }
}
